package com.shenqi.parking.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.UUID;

/**
 * Aliyun OSS 工具类
 */

public class OSSUtil {
    private final OSS ossClient;
    private final String bucketName;
    private final String endpoint;
    // 图片CND域名前缀，先不要了。空着
    public static final String HTTP_STATIC_GRAYIT_TOP = "http://shenqi-park.oss-cn-shenzhen.aliyuncs.com";


    /**
     * 全参数构造器（供Spring注入使用）
     */
    public OSSUtil(String endpoint, String accessKeyId,
                   String accessKeySecret, String bucketName) {
        this.endpoint = validateParam(endpoint, "endpoint");
        this.bucketName = validateParam(bucketName, "bucketName");

        this.ossClient = new OSSClientBuilder()
                .build(
                        this.endpoint,
                        validateParam(accessKeyId, "accessKeyId"),
                        validateParam(accessKeySecret, "accessKeySecret")
                );
    }

    private String validateParam(String value, String paramName) {
        if (StringUtils.isBlank(value)) {
            throw new IllegalArgumentException("OSS参数不能为空: " + paramName);
        }
        return value;
    }

    /**
     * 上传文件到OSS
     *
     * @param filePath    本地文件路径
     * @param ossFilePath OSS文件路径（包含文件名），如："images/avatar.jpg"
     * @return 文件访问URL
     */
    public String uploadFile(String filePath, String ossFilePath) {
        if (StringUtils.isBlank(filePath) || StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        try {
            // 创建PutObjectRequest对象
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath, new File(filePath));

            // 上传文件
            ossClient.putObject(putObjectRequest);

            // 返回文件访问URL
            return generateUrl(ossFilePath);
        } catch (OSSException | ClientException e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     * 上传文件流到OSS
     *
     * @param inputStream 文件输入流
     * @param ossFilePath OSS文件路径（包含文件名），如："images/avatar.jpg"
     * @return 文件访问URL
     */
    public String uploadFile(InputStream inputStream, String ossFilePath) {
        if (inputStream == null || StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("参数不能为空");
        }

        try {
            // 创建PutObjectRequest对象
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, ossFilePath, inputStream);

            // 上传文件
            ossClient.putObject(putObjectRequest);

            // 返回文件访问URL
            return generateUrl(ossFilePath);
        } catch (OSSException | ClientException e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     * 上传字节数组到OSS
     *
     * @param bytes       字节数组
     * @param ossFilePath OSS文件路径（包含文件名），如："images/avatar.jpg"
     * @return 文件访问URL
     */
    public String uploadFile(byte[] bytes, String ossFilePath) {
        if (bytes == null || bytes.length == 0 || StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("参数不能为空");
        }

        try {
            // 创建PutObjectRequest对象
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    bucketName,
                    ossFilePath,
                    new ByteArrayInputStream(bytes)
            );

            // 上传文件
            ossClient.putObject(putObjectRequest);

            // 返回文件访问URL
            return generateUrl(ossFilePath);
        } catch (OSSException | ClientException e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     * 断点续传上传大文件
     *
     * @param filePath    本地文件路径
     * @param ossFilePath OSS文件路径（包含文件名），如："videos/large.mp4"
     * @return 文件访问URL
     */
    public String uploadBigFile(String filePath, String ossFilePath) {
        if (StringUtils.isBlank(filePath) || StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("文件路径不能为空");
        }

        try {
            // 创建断点续传上传请求
            UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, ossFilePath);
            // 设置本地文件路径
            uploadFileRequest.setUploadFile(filePath);
            // 设置并发线程数，默认1
            uploadFileRequest.setTaskNum(5);
            // 设置分片大小，默认100KB
            uploadFileRequest.setPartSize(1024 * 1024);
            // 开启断点续传，默认关闭
            uploadFileRequest.setEnableCheckpoint(true);

            // 断点续传上传
            ossClient.uploadFile(uploadFileRequest);

            // 返回文件访问URL
            return generateUrl(ossFilePath);
        } catch (Throwable e) {
            throw new RuntimeException("大文件上传失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成CND链接，主要是为了公共访问
     *
     * @param ossFilePath
     * @return
     */
    public String generateCdnUrl(String ossFilePath) {
        return HTTP_STATIC_GRAYIT_TOP + ossFilePath;
    }

    /**
     * 生成文件访问URL（默认有效期1小时）
     *
     * @param ossFilePath OSS文件路径
     * @return 文件访问URL
     */
    public String generateUrl(String ossFilePath) {
        return generateUrl(ossFilePath, 3600);
    }

    /**
     * 生成文件访问URL
     *
     * @param ossFilePath OSS文件路径
     * @param expiration  URL有效期（秒）
     * @return 文件访问URL
     */
    public String generateUrl(String ossFilePath, int expiration) {
        if (StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("OSS文件路径不能为空");
        }

        try {
            // 设置URL过期时间
            Date expirationDate = new Date(System.currentTimeMillis() + expiration * 1000);
            // 生成URL
            URL url = ossClient.generatePresignedUrl(bucketName, ossFilePath, expirationDate);
            return url.toString();
        } catch (OSSException | ClientException e) {
            throw new RuntimeException("生成文件URL失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除OSS文件
     *
     * @param ossFilePath OSS文件路径
     */
    public void deleteFile(String ossFilePath) {
        if (StringUtils.isBlank(ossFilePath)) {
            throw new IllegalArgumentException("OSS文件路径不能为空");
        }

        try {
            ossClient.deleteObject(bucketName, ossFilePath);
        } catch (OSSException | ClientException e) {
            throw new RuntimeException("删除文件失败: " + e.getMessage(), e);
        }
    }

    public String uploadImage(InputStream inputStream, String fileName, String bucketDir) throws IOException {
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        String objectName = "/" + bucketDir + "/" + UUID.randomUUID() + "." + extension;

        ObjectMetadata meta = new ObjectMetadata();
        meta.setContentType(getImageContentType(extension));
        meta.setContentDisposition("inline; filename=\"" + fileName + "\"");

        ossClient.putObject(bucketName, objectName, inputStream, meta);
        return generateCdnUrl(objectName);
    }

    private String getImageContentType(String extension) {
        switch (extension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "webp":
                return "image/webp";
            case "svg":
                return "image/svg+xml";
            default:
                return "application/octet-stream";
        }
    }

    /**
     * 关闭OSS客户端（JVM退出时手动调用）
     */
    public void shutdown() {
        if (ossClient != null) {
            ossClient.shutdown();
        }
    }

}